﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;

namespace mw2admintool
{
	public class livetranslate
	{
		public String translate_url, lastError;
		public static Dictionary<String, String> langs;
		public Stack<translaterequest> queue = new Stack<translaterequest>();
		public System.Threading.ReaderWriterLockSlim echoLock = new System.Threading.ReaderWriterLockSlim();
		public delegate void receiveMessageDel(admintool.command cmd, String msg);
		public enum transtatus
		{
			toobusy,
			sent
		};
		public class translaterequest
		{
			public String from, to, msg;
			public admintool.command cmd;
			public receiveMessageDel recvCv;
			public translaterequest(admintool.command cmd, String from, String to, String msg, receiveMessageDel recvcb)
			{
				this.recvCv = recvcb;
				this.cmd = cmd;
				this.from = from;
				this.to = to;
				this.msg = msg;
			}
		}
		public void request_thread(Object data)
		{
			try
			{
				translaterequest req = data as translaterequest;
				String outstr = "";
				if (this.request(this.getUrl(req.from, req.to, req.msg), ref outstr))
				{
					echoLock.EnterWriteLock();
					req.recvCv(req.cmd, "Translator(" + req.from + "-" + req.to + "): " + outstr);
					echoLock.ExitWriteLock();
				}
			}
			catch (Exception e)
			{
				aIW.Log.Debug("Request thread error: " + e.ToString());
			}
		}

		public livetranslate(String url, String lang)
		{
			langs = new Dictionary<string,string>();
			this.translate_url = url;
			String[] p = lang.Split(';');
			String real = "";
			/*aIW.Log.Debug("Using url " + url + " and " + lang + " for Live Translator." +
				"There are " + p.Length + " alias groups.");*/
			foreach (String s in p)
			{
				String[] aliases = s.Split(',');
				if (aliases.Length == 0)
					continue;
				real = aliases[0].Trim().ToLower();
				foreach (String alias in aliases)
				{
					if (langs.ContainsKey(alias.Trim().ToLower()))
						aIW.Log.Debug("Duplicated language alias: " + alias);
					else
						langs.Add(alias.Trim().ToLower(), real);
				}
			}
			this.lastError = "";
			System.Threading.ThreadPool.SetMaxThreads(3, 1);
			System.Threading.ThreadPool.SetMinThreads(1, 1);
		}
		public bool isValidLang(String lang) { return langs.ContainsKey(lang); }

		public String getUrl(String from, String to, String subject)
		{
			if (!this.isValidLang(from) || !this.isValidLang(to))
				throw new Exception("Invalid language translation: " + from + "-" + to);
			return String.Format(this.translate_url, new Object[] { Uri.EscapeDataString(subject), from, to });
		}
		public bool request(String url, ref String outstr)
		{
			aIW.Log.Debug("Performming http request for url: " + url);
			HttpWebResponse response = null;
			String respstr = "";
			Encoding enc = Encoding.Unicode;
			try
			{
				int timeout = 1000;
				HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
				request.Method = "GET";
				request.Accept = "*/*";
				request.Headers["Accept-Encoding"] = "gzip";
				request.Headers["Accept-Charset"] = enc.HeaderName;
				request.UseDefaultCredentials = true;
				int.TryParse(admintool.settings["webrequest_timeout"], out timeout);
				request.Timeout = timeout;
				response = (HttpWebResponse)request.GetResponse();
				if (response.StatusCode != HttpStatusCode.OK)
					throw new Exception("Server did not return OK!");
				try { enc = Encoding.GetEncoding(response.CharacterSet); }
				catch (Exception) { enc = Encoding.Unicode; }
				respstr = (new System.IO.StreamReader(response.ContentEncoding != "gzip" ? response.GetResponseStream() :
					(new System.IO.Compression.GZipStream(response.GetResponseStream(), System.IO.Compression.CompressionMode.Decompress)),
					enc ).ReadToEnd());
				Match m = Regex.Match(respstr, "\\[{3}\\s*\".+?\"");

				if (!m.Success)
					throw new Exception("Could not match response string");
				respstr = Regex.Replace(Regex.Replace(m.Value, "\\[{3}", ""), "\"", "");
			}
			catch (Exception e)
			{
				aIW.Log.Debug("Web request error: " + e.ToString());
			}
			if (respstr != "")
				outstr = respstr;
			if (response != null)
				response.Close();
			return respstr != "";
		}
		public bool readConversion(String token, ref String from, ref String to)
		{
			String[] parts = token.Split('-');
			if (parts.Length != 2)
				return false;
			parts[0] = parts[0].ToLower();
			parts[1] = parts[1].ToLower();
			if (!langs.ContainsKey(parts[0]) || !langs.ContainsKey(parts[1]))
				return false;
			from = langs[parts[0]];
			to = langs[parts[1]];
			return true;
		}
		public transtatus translate(admintool.command cmd, String msg, String from, String to, receiveMessageDel receiveMessageCallback)
		{
			translaterequest req = new translaterequest(cmd, from, to, msg, receiveMessageCallback);
			System.Threading.Thread th = new System.Threading.Thread(this.request_thread);
			th.Start(new translaterequest(cmd, from, to, msg, receiveMessageCallback));
			//return transtatus.toobusy;
			return transtatus.sent;
		}
	}
}
